﻿# -*- coding:utf-8 -*-
#
# склад
#
import datetime
from django.shortcuts import render_to_response
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from django.template import RequestContext, Context
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.db.models import Sum

from sklad.forms import DocumentForm, ReceiptForm, DeliveryForm
from sklad.models import Category, Part, Document, DocumentReceipt, DocumentDelivery, Unit, Waybill, DocumentItem
from shm.models import Department

from sklad.contextprocessors import category_proc




@login_required
@permission_required('sklad.view_document')
def list_open(request):
    documents = Document.objects.filter(state='N')  
    context = Context({
      'documents' : documents,
      'current_menu_item' : '3',
      'current_sub_menu_item':'1',#list_open
    })    
    return render_to_response('sklad/document_list_open.html', context, context_instance=RequestContext(request, processors=[category_proc]))



@login_required
@permission_required('sklad.view_document')
def list_all(request):
    documents = Document.objects.select_related().all()  
    if len(documents) != 0:
        paginator = Paginator(documents, 16) # Show 16 item per page
        try:
            page = int(request.GET.get('page', '1'))
        except ValueError:
            page = 1
        try:
            documents = paginator.page(page)
        except (EmptyPage, InvalidPage):
            documents = paginator.page(paginator.num_pages)
    else:
        documents = None
    context = Context({
      'documents' : documents,
      'current_menu_item' : '3',
      'current_sub_menu_item':'2',
    })    
    return render_to_response('sklad/document_list_all.html', context, context_instance=RequestContext(request, processors=[category_proc]))


@login_required
@permission_required('sklad.delete_document')
def delete(request, document_id):
    document = get_object_or_404(Document, id = document_id)
    # Проверка на открытый документ( только открытый можно удалить)
    if document.state == 'R':
        #request.user.message_set.create(message="<font color='red'>Документ закрыт. Удалить можно только открытый документ.</font>")
        messages.warning(request, 'Документ закрыт. Удалить можно только открытый документ!')
        return HttpResponseRedirect(request.session["prev_request_path"])
    document.delete()    
    return HttpResponseRedirect(reverse('document_all', args=[]))    

 

@login_required
@permission_required('sklad.receipt_part')
def receipt_add_part(request, part_id):

    document = None
    documents = Document.objects.filter(state='N', kind='R')
    if len(documents) == 0:
        # создание документа
        document = Document(kind='R', name='Документ прихода', user=request.user, state='N')
        document.save()
        
    elif len(documents) > 1:
        # много документов - выбор
        pass  
  
    elif len(documents) == 1: 
        # один открытый документ - используем
        document = documents[0]
    part = get_object_or_404(Part, id = part_id)

    if request.method == 'POST':
        form = DocumentForm(request.POST) 
        if form.is_valid(): 
        
            '''        
            newdocument = form.save(commit=False)
            newdocument.user = request.user
            newdocument.kind = 'R'
            newdocument.state = 'N' 
            newdocument.save()
            '''
        #    docitem = form.save()
            
            #print docitem.quantity
        #    for i in xrange(docitem.quantity):
        #        partitem = PartItem(part=part, document_in=docitem, document_state='N')
        #        partitem.save()
           
            return HttpResponseRedirect(reverse('ktit.storage.views.documents.document_property', args=[document.id])) 
    else:
        form = DocumentForm(instance=document)

    context = Context({
      'form':form,
      'documents' : documents,
      'document': document,
      'part' : part,
    })
    return render_to_response('sklad/document_receipt_add_part.html', context, context_instance=RequestContext(request, processors=[category_proc]))




@login_required
@permission_required('sklad.delivery_part')
def delivery_add_part(request, part_id):
    document = None
    documents = Document.objects.filter(state='N', kind='D')
    if len(documents) == 0:
        # создание документа
        document = Document(kind='D', name='Документ выдачи', user=request.user, state='N')
        document.save()
    elif len(documents) > 1:
        # много документов - выбор
        pass  
    elif len(documents) == 1: 
        # один открытый документ - используем
        document = documents[0]
    part = get_object_or_404(Part, id = part_id)

    if request.method == 'POST':
        form = DocumentForm(request.POST)   
        #if form.is_valid(): 
        #    docitem = form.save()
        #    partitem = PartItem.objects.filter(part=part)
        #    for item in partitem[:docitem.quantity]:
        #        item.document_out=docitem
        #        item.document_state='N'
        #        item.save()
        #    return HttpResponseRedirect(reverse('ktit.storage.views.documents.document_property', args=[document.id])) 
    else:
        form = DocumentForm(instance=document)

    context = Context({
      'form':form,
      'documents' : documents,
      'document': document,
      'part' : part,
    })
    return render_to_response('sklad/document_delivery_add_part.html', context, context_instance=RequestContext(request, processors=[category_proc]))



def get_document(documents, kind, name, user):
    document = None
    # создание документа
    if len(documents) == 0:
        document = Document(kind=kind, name=name, user=user, state='N')
        document.save()
    # много документов - выбор    
    elif len(documents) > 1:
        pass  
    # один открытый документ - используем
    elif len(documents) == 1: 
        document = documents[0]    
    return document
   



#
# Запись запчасти в документ в единичном количестве без формы
# 
@login_required
@permission_required('sklad.receipt_part')
def to_receipt(request, part_id):
    documents = Document.objects.filter(state='N', kind='R')
    document = get_document(documents, 'R', 'Документ прихода', request.user)
    # get Part
    part = get_object_or_404(Part, id = part_id)
    #
    # Проверка на наличие добавляемой запчасти в документе
    from django.core.exceptions import ObjectDoesNotExist
    try:
        document_item = DocumentItem.objects.get(document = document, part = part)
        #request.user.message_set.create(message="<font color='green'>Эта позиция уже существует в документе. Количество увеличено.</font>")
        messages.success(request, 'Эта позиция уже существует в документе. Количество увеличено.') 
        
        document_item.quantity = document_item.quantity + 1
        document_item.save()
    except ObjectDoesNotExist: 
        # Create new DocItem
        docitem = DocumentItem(document = document, part = part, quantity = 1, inventory='')
        docitem.save()
     
    return HttpResponseRedirect(reverse('document_detail', args=[document.id]))  
    


@login_required    
@permission_required('sklad.delivery_part')
def to_delivery(request, part_id): 
    documents = Document.objects.filter(state='N', kind='D')
    document = get_document(documents, 'D', 'Документ выдачи', request.user)
    # get Part
    part = get_object_or_404(Part, id = part_id)
    #
    # проверка на наличие запчасти на складе в достаточном количестве
    count = Waybill.objects.filter(part=part).aggregate(Sum("count"))
    if count["count__sum"] < 1:
        #request.user.message_set.create(message="<font color='red'>Нельзя выдать эту позицию. Отсутствует на складе.</font>")
        messages.warning(request, 'Нельзя выдать эту позицию. Отсутствует на складе.')
        return HttpResponseRedirect(reverse('category_view', args=[part.category.id])) 
    
    # Проверка на наличие добавляемой запчасти в документе
    from django.core.exceptions import ObjectDoesNotExist
    try:
        document_item = DocumentItem.objects.get(document = document, part = part)
        if (document_item.quantity + 1) > count["count__sum"]:
            #request.user.message_set.create(message="<font color='red'>Нельзя выдать эту позицию. Количество на складе ограничено.</font>")
            messages.warning(request, 'Нельзя выдать эту позицию. Количество на складе ограничено.')
            return HttpResponseRedirect(reverse('category_view', args=[part.category.id])) 
        else:    
            #request.user.message_set.create(message="<font color='green'>Эта позиция уже существует в документе. Количество увеличено.</font>")
            messages.success(request, 'Эта позиция уже существует в документе. Количество увеличено.') 
            document_item.quantity = document_item.quantity + 1
            document_item.save()
        #return HttpResponseRedirect(reverse('document_detail', args=[document.id])) 
    except ObjectDoesNotExist:   
        # Create new DocItem
        docitem = DocumentItem(document = document, part = part, quantity = 1, inventory='' )
        docitem.save()   
   
    return HttpResponseRedirect(reverse('document_detail', args=[document.id]))  




@login_required
@permission_required('sklad.view_document')
def detail(request, doc_id):
    document = get_object_or_404(Document, id = doc_id)
    document_items = DocumentItem.objects.select_related().filter(document = doc_id)
    new_document = True
    document_receipt = None
    document_delivery = None
    if document.state == 'R':
        new_document = False    
        if document.kind == 'R':
            document_receipt = DocumentReceipt.objects.get(document=document)
        if document.kind == 'D':
            document_delivery = DocumentDelivery.objects.get(document=document)
   
    if request.method == 'POST':
        register_document_flag = request.POST.has_key('register_document')
        if request.POST.has_key('save_document_detail') or register_document_flag: 
            if request.POST.has_key('doc_comment'):
                document_comment =  request.POST['doc_comment']
                document.comment=document_comment
                document.save()
            quantity_id = [x for x in request.POST if x.startswith('part_quantity_id_')]
            part_quantity=[]
            for item in quantity_id:
                part_quantity.append({"id":int(item.replace('part_quantity_id_', '')), "name":item, "value":request.POST[item]})
            for item in part_quantity:
                # проверка на ноль
                if int(item['value']) > 0:
                    #Проверка на количество!(только для document.kind == 'D')
                    if document.kind == 'D':
                        docitem = get_object_or_404(DocumentItem, id = item['id'])
                        count = Waybill.objects.filter(part = docitem.part).aggregate(Sum("count"))
                        if int(item['value']) > count["count__sum"]:
                            #request.user.message_set.create(message="<font color='red'>Выбрано количество, больше чем на складе.</font>")
                            messages.warning(request, 'Выбрано количество, больше чем в наличии на складе.')
                            item['value'] = count["count__sum"]
                    DocumentItem.objects.filter(id = item['id']).update(quantity=item['value'])    
                else:
                    DocumentItem.objects.filter(id = item['id']).delete()
            #
            if register_document_flag:
                return HttpResponseRedirect(reverse('document_register', args=[doc_id]))
        
    context = Context({
      'document' : document,
      'document_items':document_items,
      'document_receipt':document_receipt,
      'document_delivery':document_delivery,
      'new':new_document,
    })    
    return render_to_response('sklad/document_detail.html', context, context_instance=RequestContext(request, processors=[category_proc]))
    

@permission_required('sklad.receipt_part')
def receipt_register(request, document):
    import datetime
    document_items = DocumentItem.objects.select_related().filter(document = document)
    if request.method == 'POST':
        form = ReceiptForm(request.POST)
        if form.is_valid():
            receipt = form.save(commit=False)
            receipt.document = document
            # Выполнение всех операций в одной транзакции
            from django.db import transaction
            transaction.enter_transaction_management()
            try:
                transaction.managed(True)
                #
                for item in document_items:
                    waybill = Waybill(document=document, doc='rec', part=item.part, unit=item.part.unit, count=item.quantity, description='',user=document.user )
                    waybill.save()
                receipt.save()
                document.state = 'R'
                document.date_reg = datetime.datetime.now()
                document.save()
                #
                transaction.commit()
            finally:
                transaction.rollback()
                transaction.leave_transaction_management()
            return HttpResponseRedirect(reverse('document_all', args=[]))
    else:
        form = ReceiptForm()
    context = Context({
      'document' : document,
      'document_items':document_items,
      'form':form,
    }) 
    return render_to_response('sklad/form_receipt_register.html', context, context_instance=RequestContext(request, processors=[category_proc]))
    

@permission_required('sklad.delivery_part')    
def delivery_register(request, document):
    import datetime
    document_items = DocumentItem.objects.select_related().filter(document = document)
    if request.method == 'POST':
        form = DeliveryForm(request.POST)
        if form.is_valid():
            delivery = form.save(commit=False)
            delivery.document = document
            # Выполнение всех операций в одной транзакции
            from django.db import transaction
            transaction.enter_transaction_management()
            try:
                transaction.managed(True)
                #
                for item in document_items:
                    waybill = Waybill(document=document, doc='del', part=item.part, unit=item.part.unit, count=item.quantity*(-1), description='',user=document.user, department=delivery.department, person=delivery.person, phone=delivery.phone)
                    waybill.save()
                delivery.save()
                document.state = 'R'
                document.date_reg = datetime.datetime.now()
                document.save()
                #
                transaction.commit()
            finally:
                transaction.rollback()
                transaction.leave_transaction_management()
            return HttpResponseRedirect(reverse('document_all', args=[]))
    else:
        form = DeliveryForm()
    context = Context({
      'document' : document,
      'document_items':document_items,
      'form':form,
    }) 
    return render_to_response('sklad/form_delivery_register.html', context, context_instance=RequestContext(request, processors=[category_proc]))




@login_required
def register(request, document_id):
    document = get_object_or_404(Document, id = document_id)
    # Проверка на открытый документ( только открытый можно зарегить)
    if document.state == 'R':
        #request.user.message_set.create(message="<font color='red'>Документ закрыт. Зарегистрировать можно только открытый документ.</font>")
        messages.warning(request, 'Документ закрыт. Зарегистрировать можно только открытый документ.')
        return HttpResponseRedirect(reverse('document_detail', args=[document.id]))  
    #
    if document.kind == 'R':
        return receipt_register(request, document)
    else:# document.kind == 'D':
        return delivery_register(request, document)
        



